package cz.possoft.client.gui.panel;

import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JPanel;

import layout.TableLayout;
import cz.possoft.client.gui.dialog.SimpleDialog;
import cz.possoft.client.gui.gamepanel.components.GamePane;
import cz.possoft.client.gui.panel.nastavenispodnipanel.panel.NastaveniShowPanel;
import cz.possoft.client.utils.GameInvocationUtils;
import cz.possoft.client.utils.PanelHolderUtils;
import cz.possoft.messages.PropertiesManager;
import cz.possoft.messages.Text;
import cz.possoft.serializable.generic.Game;
import cz.possoft.serializable.generic.Location;

/**
  *
  * @author mara
  *
  * hlavni herni panel aplikace vlevo nahore. V panelu je zobrazen
  * jeste podrazeny panel urcite hry podle kontextu hry
  */
public abstract class GamePanel extends JPanel {	
	
	// identifikatory specialnich udalosti
	public static int EVENT_CHESS_PESEC_DOSEL = 0;
	public static int EVENT_CHESS_VYBRANA_FIGURKA = 1;	
	
    // TextPane na kterym je nakresleno hraci pole (napr. sachovnice)
    private GamePane gamePane;
    
    // instance jedne hry
    private Game game;
    
    // mark jestli uz byla oznacena figurka pro tah
    private boolean marked;

    // umisteni oznacene figurky (v pripade ze byla oznacena)
    private Location markedFigurkaForPlay;

    // umisteni figurky nad kterou je prstenec, ale nebyla oznacena pro tah
    private Location ringFigurka;    
    
    // Applet ve kterem je toto umisteno
    static JApplet applet;   
    
    // label s napisem 'Jouda je na tahu.'
    private JLabel vrchniLabel;
    
    // labely s jmenama hracu
    private JLabel clientNameLabel;
    private JLabel opponentNameLabel;
    
    // label s oznamenim, ze ma nekdo sach
    private JLabel sachLabel;    
    
    // label, kde se zobrazuje tah posledni figurky
    private JLabel lastTahLabel; 
    
    // prefix hry. Napriklad 'Chess' pro sachy
    private String gameClassPrefix;
    
    double[][] fieldSize = {{25, 25, 250, 100, 100, 25, 125}, {15, 30, 210, 30, 210, 25}};        	    
    
    public GamePanel() {
    	applet = PanelHolderUtils.getApplet();
    }
    
    /** Creates a new instance of GamePanel */
    public GamePanel(JApplet app) {
    	applet = app;
    }
    
    public void setGameClassPrefix(String gameClassPrefix) {
    	this.gameClassPrefix = gameClassPrefix;
    }
    
    public String getGameClassPrefix() {
    	return gameClassPrefix;
    }
    
    /**
     * Return human-readable name for game. For example "Sachy" for Chess.
     */
    public String getDisplayName() {
    	return PropertiesManager.getInstance().getMessageForKey(gameClassPrefix + ".display", getGameClassPrefix());
    }
    
    // inicializuje komponenty, ktere by mely byt specificke pro vsechny hry.
    // Metoda by vsak mela byt pretizena u potomku, kteri by meli volat super.
    protected void initComponents() {
        setLayout(new TableLayout(fieldSize));
        add(getVrchniLabel(), "2,1");
        add(getOpponentNameLabel(), "6,2");
        add(getClientNameLabel(), "6,4");        
        add(getGamePane(), "2,2,4,4");        
        add(getSachLabel(), "6,3");        
        add(getLastTahLabel(), "3,1,6,1");
    }    
    
    // volame gamePane aktualni hry.
    public GamePane getGamePane() {
        if (gamePane == null) {
            gamePane = GameInvocationUtils.getInstanceOfGamePane(gameClassPrefix, getGame().getHraciPole());
            gamePane.setEditable(false);
        }
        return gamePane;
    } 
    
    public Game getGame() {
        return game;
    } 
    
    public void setGame(Game game) {
    	this.game = game;
    }
    
    protected JLabel getOpponentNameLabel() {
        if (opponentNameLabel == null) {
        	opponentNameLabel = new JLabel("");
        	opponentNameLabel.setVerticalAlignment(JLabel.TOP);
        }
        return opponentNameLabel;
    }

    public JLabel getVrchniLabel() {
        if (vrchniLabel == null) {
            vrchniLabel = new JLabel("");
            vrchniLabel.setVerticalAlignment(JLabel.TOP);
        }
        return vrchniLabel;
    }        
    
    public JLabel getLastTahLabel() {
        if (lastTahLabel == null) {
            lastTahLabel = new JLabel("");
            lastTahLabel.setVerticalAlignment(JLabel.TOP);
        }
        return lastTahLabel;
    }     

    protected JLabel getClientNameLabel() {
        if (clientNameLabel == null) {
        	clientNameLabel = new JLabel("");
        	clientNameLabel.setVerticalAlignment(JLabel.BOTTOM);
        }
        return clientNameLabel;
    }

    public JLabel getSachLabel() {
        if (sachLabel == null) {
            sachLabel = new JLabel("");
            sachLabel.setVerticalAlignment(JLabel.CENTER);
        }
        return sachLabel;
    }   
    
    public boolean isMarked() {
        return marked;
    }

    public void setMarked(boolean marked) {
        this.marked = marked;
    }

    public Location getMarkedFigurkaForPlay() {
        return markedFigurkaForPlay;
    }

    public void setMarkedFigurkaForPlay(Location markedFigurka) {
        this.markedFigurkaForPlay = markedFigurka;
    }

    public Location getRingFigurka() {
        return ringFigurka;
    }

    public void setRingFigurka(Location ringFigurka) {
        this.ringFigurka = ringFigurka;
    }

    protected static String addHtmlTagsToLabels(String labText, String color, char size) {
        return "<HTML><BODY><FONT COLOR=" + color + " SIZE=" + size + "><I>" + labText + "</I></FONT></BODY></HTML>";
    }    
    
    // Tato metoda zavola setGame a pote provede nezbytne inicialni
    // kroky pri nasetovani teto hry (prekresleni panelu atd.)
    // metoda by mela byt vzdy pretizena a potomek by mel vzdy volat super
    public void setAndInitGame(Game gam) {
        setGame(gam);        
        if (game.isGameBegin()) {
        	String clientName = game.isMeWhite() ? game.getWhitePlayerName() : game.getBlackPlayerName();
        	String opponentName = game.isMeWhite() ? game.getBlackPlayerName() : game.getWhitePlayerName();
            getOpponentNameLabel().setText(addHtmlTagsToLabels(opponentName, "BLUE", '5'));
            getClientNameLabel().setText(addHtmlTagsToLabels(clientName, "BLUE", '5'));
            String hracNaTahu = game.isWhiteNaTahu() ? game.getWhitePlayerName() : game.getBlackPlayerName();
            getVrchniLabel().setText(Text.getPlayerNaTahu(hracNaTahu));              
            getLastTahLabel().setText(PropertiesManager.getInstance().getMessageForKey(Text.POSLEDNI_TAH));
            // enablovani tlacitka 'odeslat' u ChatPanelu
            ChatPanel.getSendButton().setEnabled(true);
        } else {
            getOpponentNameLabel().setText("");
            getClientNameLabel().setText("");
            getVrchniLabel().setText("");
            getLastTahLabel().setText("");
            // disablovani tlacitka 'odeslat' u ChatPanelu
            ChatPanel.getSendButton().setEnabled(false);
        }    	
    }
    
    // Tato metoda je volana az po tom, co je panel instanciovan.        
    // Inicializace panelu
    public void init() {
       	game = GameInvocationUtils.getInstanceOfGame(getGameClassPrefix());
    	setGame(game);
        game.setNoGame();
        setEndStateToGame(false);
        setActiveToGame(false);
        initComponents();               	  
    }           
    
    /** Called during undeployment. Some cleaning operations should be here when needed on subclasses of GamePanel. */
    public void destroy() {
    	if (getGame().isActive()) {
    		SimpleDialog.getInstance("Preruseni hry - TODO", "Hra musela byt nenadale prerusena. TODO");
    	   	// TODO: dat sem neco lepsiho nez zrovna PROHRA_NAVRH: . Oponent by mel byt informovan, ze nam to spadlo. Ne ze vyhral.
            NastaveniShowPanel.getConnectThread().sendToServer("PROHRA_NAVRH: ");
            setActiveToGame(false);
            setEndStateToGame(true);    	    		
    	}
    }
    
    // ziskani nadrazeneho appletu (promenna applet)
    public JApplet getApplet() {
        return applet;
    }
    
    // metoda uvolni oponenta a zasle o tom info na server (tzn. muzu vyzvat jineho hrace a jiny muze vyzvat me)
    // je volana ze setActive
    protected static void setNoOpponent() {
        if (NastaveniShowPanel.getConnectThread() != null) {
            NastaveniShowPanel.getConnectThread().setOpponentName("");
            NastaveniShowPanel.getConnectThread().sendToServer("I_AM_FREE: ");
        }
    }  
    
    // nastavi endState zvolene hre a provede pridruzene akce
    public void setEndStateToGame(boolean endState) {
    	getGame().setEndState(endState);        
        NastaveniVrchniPanel.getUlozeniMenuButton().setEnabled(!endState && getGame().isGameBegin());    	 
    }
    
    // nastavi active u hry a provede pridruzene akce
    public void setActiveToGame(boolean active) {
    	getGame().setActive(active);
        this.setRingFigurka(new Location(-1, -1));
        this.setMarkedFigurkaForPlay(new Location(-1, -1));
        this.setMarked(false);        
        
        NastaveniVrchniPanel.getNacteniMenuButton().setEnabled(active);
        
        NastaveniVrchniPanel.getRemizaMenuButton().setEnabled(active);
        NastaveniVrchniPanel.getProhraMenuButton().setEnabled(active);
        this.getGamePane().repaint();
        if (active == false) {
            setNoOpponent();       
            if (ChatPanel.getSendButton() != null) {
                ChatPanel.getSendButton().setEnabled(false);
            }
            NastaveniSpodniPanel.getNastaveniSpodniPanel().remizaLabelFakeClean();            
            NastaveniSpodniPanel.getNastaveniSpodniPanel().nastaveniStisknuto();
        }    	    	    	
    }
    
    // prime odehrani tahu bez kontrol markupu a ringu atd. Tato metoda je volana
    // u aktivniho hrace i u protihrace (po tom co obdrzi muj tah ze serveru)
    // metoda by mela vzdy byt pretizena potomkem a potomek by mel vzdy volat super
    public void doPlay(int oldX, int oldY, int newX, int newY) {
        // nastaveni labelu atd
        getGame().setWhiteNaTahu(!this.getGame().isWhiteNaTahu());        
        getVrchniLabel().setText(Text.getPlayerNaTahu(getGame().isWhiteNaTahu() ? getGame().getWhitePlayerName() : getGame().getBlackPlayerName()));    	
    }
    
    // Metoda zajistuje spusteni specialni udalostin na danem panelu. U hry sachy je to napriklad dojiti pesce do 
    // cile a s tim souvisejici spusteni dialogu.
    public void performSpecialEvent(int eventId, String eventString) {};

}
